package alarmdisplay;

import gnu.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;
import java.io.*;
import java.util.*;
import java.net.*;
import java.util.Calendar;
import javax.swing.*;
import java.awt.*;
import java.text.SimpleDateFormat;

public class ComListener implements Runnable {

    private static boolean DEBUG = true;
    private static int iPort = 0;
    private static int iPort2 = 0;
    private static String strIP = "";
    private static String portName = "";
    private static String sNachricht = "";
    private boolean bAnzeigeDefekt = false;

    private static SimpleDateFormat formater = new SimpleDateFormat();

    CommPortIdentifier serialPortId;
    Enumeration<?> enumComm;
    SerialPort serialPort;
    InputStream inputStream;
    Boolean serialPortGeoeffnet = false;

    int baudrate = 9600;
    int dataBits = SerialPort.DATABITS_8;
    int stopBits = SerialPort.STOPBITS_1;
    int parity = SerialPort.PARITY_NONE;

    /**
     * @param args
     */
    public static void main(String[] args) {
        Debug.debug("COMLISTENER", "ComListener V1.41 (" + formater.format(Calendar.getInstance().getTime()) + ")");
        System.out.println("Start");
        Datenbank db = new Datenbank();
        DEBUG = Boolean.valueOf(db.dbQueryConfig("comlistener_debug"));
        try {
            if (DEBUG) {
                System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out), true, "CP850"));
            }
        } catch (Exception err) {
            System.out.println("GEHT NICHT!!!!" + err);
        }
        if (DEBUG) {
            System.out.println("!!!! Default Encoding = " + System.getProperty("file.encoding"));
        }

        Debug.debug("COMLISTENER", "DEBUG>>    Parameter DEBUG: " + DEBUG);
        portName = db.dbQueryConfig("comlistener_port");
        strIP = db.dbQueryConfig("comlistener_sender_ip");
        iPort = Integer.parseInt(db.dbQueryConfig("comlistener_sender_port"));
        Debug.debug("COMLISTENER", "DEBUG>>       Parameter IP: " + strIP);
        Debug.debug("COMLISTENER", "DEBUG>> Parameter COM-Port: " + portName);
        Debug.debug("COMLISTENER", "DEBUG>>     Parameter Port: " + iPort);

        iPort2 = Integer.parseInt(db.dbQueryConfig("comlistener_service_port"));
        Debug.debug("COMLISTENER", "DEBUG>>    Parameter Port2: " + iPort2);

        JFrame jf = new JFrame();
        JPanel jp = new JPanel(new GridLayout(3, 1));
        jf.getContentPane().add(jp);
        jf.setTitle("ComListener");
        jf.setLocation(0, 0);
        jf.setSize(200, 400);
        jf.setSize(200, 400);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel jl1 = new JLabel("      Parameter IP: " + strIP);
        JLabel jl2 = new JLabel("Parameter COM-Port: " + portName);
        JLabel jl3 = new JLabel("    Parameter Port: " + iPort);
        jp.add(jl1);
        jp.add(jl2);
        jp.add(jl3);
        jf.setVisible(true);

        Runnable runnable = new ComListener();
        new Thread(runnable).start();
        Debug.debug("COMLISTENER", "DEBUG>> main finished");
    }

    /**
     *
     */
    public ComListener() {
    }

    public void run() {
        schliesseSerialPort();
        if (oeffneSerialPort(portName) != true) {
            Debug.debug("COMLISTENER", "ERROR>> oeffneSerialPort()");
        }
        Debug.debug("COMLISTENER", "DEBUG>> Warten auf Nachricht...");

	//
        // Dieser Teil für Ping an Anzeige
        //
        /*
         while (true) {
         try {
         if (sNachricht.isEmpty()) {
         Thread.sleep(10000);
         TCPClient("TESTMESSAGE", true);
         }
         } catch (InterruptedException e) {
         }
         }
         */
	//
        // Dieser Teil für Test's mit ComListener
        //
        try {
            ServerSocket listen = new ServerSocket(iPort2);
            while (true) {
                getConnection(listen.accept());
            }
        } catch (IOException err) {
            Debug.debug("COMLISTENER", "ERROR>> [TCPServer]: " + err.toString());
        }

    }

    boolean oeffneSerialPort(String portName) {
        Boolean foundPort = false;
        if (serialPortGeoeffnet != false) {
            Debug.debug("COMLISTENER", "ERROR>> Serialport bereits geöffnet");
            return false;
        }
        Debug.debug("COMLISTENER", "DEBUG>> Oeffne Serialport: " + portName);
        enumComm = CommPortIdentifier.getPortIdentifiers();
        while (enumComm.hasMoreElements()) {
            serialPortId = (CommPortIdentifier) enumComm.nextElement();
            Debug.debug("COMLISTENER", "DEBUG>>>" + serialPortId.getName());
            if (portName.contentEquals(serialPortId.getName())) {
                foundPort = true;
                break;
            }
        }
        if (foundPort != true) {
            Debug.debug("COMLISTENER", "ERROR>> Serialport nicht gefunden: " + portName);
            return false;
        }
        try {
            serialPort = (SerialPort) serialPortId.open("Oeffnen und Senden", 500);
        } catch (PortInUseException e) {
            Debug.debug("COMLISTENER", "ERROR>> Port belegt");
        }
        try {
            inputStream = serialPort.getInputStream();
        } catch (IOException e) {
            Debug.debug("COMLISTENER", "ERROR>> Keinen Zugriff auf InputStream");
        }
        try {
            serialPort.addEventListener(new serialPortEventListener());
        } catch (TooManyListenersException e) {
            Debug.debug("COMLISTENER", "ERROR>> TooManyListenersException für Serialport");
        }
        serialPort.notifyOnDataAvailable(true);
        try {
            serialPort.setSerialPortParams(baudrate, dataBits, stopBits, parity);
        } catch (UnsupportedCommOperationException e) {
            Debug.debug("COMLISTENER", "ERROR>> Konnte Schnittstellen-Paramter nicht setzen");
        }

        serialPortGeoeffnet = true;
        return true;
    }

    void schliesseSerialPort() {
        if (serialPortGeoeffnet == true) {
            Debug.debug("COMLISTENER", "DEBUG>> Schließe Serialport");
            serialPort.close();
            serialPortGeoeffnet = false;
        } else {
            Debug.debug("COMLISTENER", "ERROR>> Serialport bereits geschlossen");
        }
    }

    void serialPortDatenVerfuegbar() {
        try {
            byte[] data = new byte[1500];
            int num;
            while (inputStream.available() > 0) {
                num = inputStream.read(data, 0, data.length);
                Debug.debug("COMLISTENER", "DEBUG>> [TEIL_EMPFANG]: " + formater.format(Calendar.getInstance().getTime()) + " --- " + new String(data, 0, num));
                sNachricht = sNachricht + new String(data, 0, num);
            }
        } catch (IOException e) {
            Debug.debug("COMLISTENER", "ERROR>> Fehler beim Lesen empfangener Daten");
            return;
        }
        Debug.debug("COMLISTENER", "DEBUG>> [GESA_EMPFANG]: " + formater.format(Calendar.getInstance().getTime()) + " --- " + sNachricht);
        schreibeInDB(sNachricht);
    }

    class serialPortEventListener implements SerialPortEventListener {

        public void serialEvent(SerialPortEvent event) {
            Debug.debug("COMLISTENER", "DEBUG>> " + formater.format(Calendar.getInstance().getTime()) + " --- Neues Event: serialPortEventlistener");
            switch (event.getEventType()) {
                case SerialPortEvent.DATA_AVAILABLE:
                    serialPortDatenVerfuegbar();
                    break;
                case SerialPortEvent.BI:
                    break;
                case SerialPortEvent.CD:
                    break;
                case SerialPortEvent.CTS:
                    break;
                case SerialPortEvent.DSR:
                    break;
                case SerialPortEvent.FE:
                    break;
                case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
                    break;
                case SerialPortEvent.PE:
                    break;
                case SerialPortEvent.RI:
                    break;
                default:
            }
        }
    }

    /**
     * Schreiben in DB
     */
    private void schreibeInDB(String str) {
        schreibeInDB(str, 0);
    }

    private int schreibeInDB(String str, int iAlarm) {
        boolean bNachrichtEnde = false;
        int iCount = 0;

        Debug.debug("COMLISTENER", "DEBUG>> Start: iAlarm = " + iAlarm);
        //
        // Test ob Nachricht mit 00 endet, dann ist sie vollstaendig
        // Evtl. aber sind auch zwei Nachrichten enthalten
        //
        char cc = str.charAt(str.length() - 1);
        if ((int) cc != 0) {
            Debug.debug("COMLISTENER", "DEBUG>> Kein 0x00 am Ende der Nachricht gefunden, stoppe Verarbeitung SchreibeInDB()");
            return 0;
        }

        for (int i = 0, size = str.length(); i < size; i++) {
            char c = str.charAt(i);
            //Debug.debug("COMLISTENER", "DEBUG>> - 1- ASCII: " + "[" + c + "]" + ((int)c));
            if ((int) c == 0) {
                bNachrichtEnde = true;
                if (i == (size - 1)) {
                    Debug.debug("COMLISTENER", "DEBUG>> ALLES GUT c: " + i + ", Size: " + size);
                    str = str.substring(0, str.length() - 1);                                                         // Nullbyte entfernen
                    break;
                } else {
                    Debug.debug("COMLISTENER", "DEBUG>>      String zu kurz: " + i + ", Size: " + size);
                    Debug.debug("COMLISTENER", "DEBUG>> Verarbeite nochmals: " + str.substring(i + 1, str.length()));
                    Debug.debug("COMLISTENER", "DEBUG>>   Verarbeite direkt: " + str.substring(0, i - 1));
                    if ((str.substring(0, i - 1).indexOf("Einsatzalarm 89") != -1) || (str.substring(0, i - 1).indexOf("Einzelfahrzeug 89") != -1)) {
                        iAlarm = schreibeInDB(str.substring(i + 1, str.length()), iAlarm + 1);                    // Rest der Zeile nochmals rekursiv verarbeiten mit Alarm-Increase

                    } else {
                        iAlarm = schreibeInDB(str.substring(i + 1, str.length()), iAlarm);                        // Rest der Zeile nochmals rekursiv verarbeiten ohne Increase
                    }
                    str = str.substring(0, i - 1);                                                                 // Nullbyte entfernen und ersten Teilstring verarbeiten
                    Debug.debug("COMLISTENER", "DEBUG>> Verarbeite direkt2: " + str);
                    break;
                }
            }
        }

        //
        // Pruefen ob das Ende der Nachricht erreicht ist
        //
        if (bNachrichtEnde) {
			boolean bAndereFeuerwehr=false;
			String strRIC = "";
            Debug.debug("COMLISTENER", "DEBUG>> ENDE DER NACHRICHT GEFUNDEN");
            //
            // RAW Nachricht in DB schreiben und Mail versenden
            //
            Datenbank db = new Datenbank();
            db.dbInsertRaw(str);

            //
            // Nachricht aufsplitten
            //
            for (int i = 0, size = str.length() - 1; i < size; i++) {
                char c1 = str.charAt(i);
                char c2 = str.charAt(i + 1);
                //Debug.debug("COMLISTENER", "DEBUG>> ASCII: " + "["+ c1 + "]" + ((int)c1) + " " + ((int)c2));
                if (((int) c1 == 13) && ((int) c2 == 10)) {
                    iCount++;
                    Debug.debug("COMLISTENER", "DEBUG>> Suche nach 13/10 " + iCount);
                    if (iCount == 2) {
                        Debug.debug("COMLISTENER", "DEBUG>> Suche nach 13/10 (2) Stelle: " + i);
                        strRIC = str.substring(i + 2, i + 2 + 3);                                                // + 2
                        Debug.debug("COMLISTENER", "DEBUG>> RIC: " + strRIC);
                        db = new Datenbank();
                        if (db.dbCheckRIC(strRIC) != true) {
                            Debug.debug("COMLISTENER", "DEBUG>> Abbruch von RIC...?");
                            sNachricht = "";											// Nachrichtenspeicher löschen (Bitte testen!!!)
                            return iAlarm;
                        }
                    }
					
                    if (iCount == 3) {
                        Debug.debug("COMLISTENER", "DEBUG>> Suche nach 13/10 (3) Stelle: " + i);
                        str = str.substring(i + 2, str.length());                                               // + 2
                        Debug.debug("COMLISTENER", "DEBUG>> Nachricht(Neu): " + str);
                        break;
                    }
                }
            }
			//
			// 19.03.2015 CRQ011
			//
			if (strRIC.startsWith(db.dbQueryConfig("Lassroenne"))) {									// Fuer die andere Feuerwehr
				Debug.debug("COMLISTENER", "DEBUG>> Lassroenne gefunden");
				bAndereFeuerwehr=true;
			}
			String strEMailCheck = db.dbQueryConfig("mail_send");
			if (strEMailCheck.equals("1")) {
				Debug.debug("COMLISTENER", "DEBUG>> smsAndEmail start");
				SendMail.smsAndEMail(bAndereFeuerwehr==true?1:-1, str);
				Debug.debug("COMLISTENER", "DEBUG>> smsAndEmail stop");
			} else {
				Debug.debug("COMLISTENER", "DEBUG>> eMail per config disabled... (emails nicht Y)");
			}

						
			if (bAndereFeuerwehr==false) {
				//
				// Wenn mehrere Alarme, dann ersetze Text
				//
				Debug.debug("COMLISTENER", "DEBUG>> Ende: iAlarm = " + iAlarm);
				if (iAlarm > 0) {
					str = str.substring(str.indexOf(":"));
					str = "Vollalarm" + str;
				}

				//
				// Nachricht versenden an Anzeige
				//
				TCPClient(str, true);
			}
			
            sNachricht = "";
        } else {
            Debug.debug("COMLISTENER", "DEBUG>> !!! KEIN ENDE DER NACHRICHT GEFUNDEN !!!" + sNachricht);
        }
        return iAlarm;
    }

    /**
     * Nachricht an Server senden. Je nach Konfiguration wird nur an einen
     * Empfaenger gesendet oder an mehrere.
     */
    private void TCPClient(String message) {
        TCPClient(message, strIP, iPort);
    }

    private void TCPClient(String message, boolean test) {
        Datenbank db = new Datenbank();
        db = new Datenbank();
        Vector<ComIPPort> v = db.dbQueryCom();
        for (int x = 0; x < v.size(); x++) {
            TCPClient(message, v.elementAt(x).sIP, v.elementAt(x).iPort);
        }
    }

    private void TCPClient(String message, String myStrIP, int myIPort) {
        Debug.debug("COMLISTENER", "DEBUG>> Versende an: " + myStrIP + ":" + myIPort + " - " + message);
        try {
            Socket s = new Socket(myStrIP, myIPort);
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream(), "UTF-8"));
            out.write(message + '\n');
            out.flush();
            out.close();
            s.close();
        } catch (Exception err) {
            Debug.debug("COMLISTENER", "Error: " + err);
            if (bAnzeigeDefekt == false) {
                Debug.debug("COMLISTENER", "DEBUG>> Erzeuge Fehler-eMail");
                SendMail sm1 = new SendMail("mail@janelvers.de", "Fehler im Display (Anzeige)\n" + err.toString(), "Fehler beim uebermitteln zur Anzeige!", "", "");
				sm1.sendMail("mail@janelvers.de", "Fehler im Display (Anzeige)\n" + err.toString(), "Fehler beim uebermitteln zur Anzeige!");
                Debug.debug("COMLISTENER", "DEBUG>> Ende Erzeuge Fehler-eMail");
                bAnzeigeDefekt = true;
                return;
            }
        }
        bAnzeigeDefekt = false;
    }

    /**
     * Listen()-Methode, damit fuer Debugzwecke Nachrichten per TCP geschickt
     * werden koennen.
     */
    public void listen() {
        try {
            ServerSocket listen = new ServerSocket(iPort2);
            while (true) {
                getConnection(listen.accept());
            }
        } catch (IOException err) {
            Debug.debug("COMLISTENER", "ERROR>> [TCPServer]: " + err.toString());
        }
    }

    /**
     * Hier wird eine Debug-Nachricht gelesen und als Standard-Com-Meldung
     * weiterverarbeitet.
     */
    public void getConnection(Socket s) {
        BufferedReader in = null;
        String str = "", strGesamt = "";
        try {
            in = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
            InetAddress ia = s.getInetAddress();
            Debug.debug("COMLISTENER", "DEBUG>> IP-Adresse: " + ia.getHostAddress());
            Debug.debug("COMLISTENER", "DEBUG>>  Host-Name: " + ia.getHostName());
            while ((str = in.readLine()) != null) {
                Debug.debug("COMLISTENER", "DEBUG>> Outputput: " + str + "--" + str.length());

                if (str.length() == 1) {
                    strGesamt = strGesamt + (char) 0 + System.getProperty("line.separator");
                } else {
                    strGesamt = strGesamt + str + System.getProperty("line.separator");
                }
            }
            strGesamt = strGesamt.substring(0, strGesamt.length() - 2);
            Debug.debug("COMLISTENER", "DEBUG>>  Empfangen: " + strGesamt);
            schreibeInDB(strGesamt);
        } catch (IOException err) {
            Debug.debug("COMLISTENER", "ERROR>> [TCPServer]: " + err.toString());
        } finally {
            try {
                in.close();
            } catch (IOException err) {
                Debug.debug("COMLISTENER", "ERROR>> in.close(): " + err);
            }
            try {
                s.close();
            } catch (IOException err) {
                Debug.debug("COMLISTENER", "ERROR>> s.close(): " + err);
            }
        }
    }
}
